﻿using HotelManagementClient.Model;
using HotelManagementClient.Utlis;
using HotelManagementClient.ViewModel;
using MaterialDesignThemes.Wpf;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.IO.Ports;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using static HslCommunication.Profinet.Knx.KnxCode;

namespace HotelManagementClient.View
{
    /// <summary>
    /// Interaction logic for OfflineCard.xaml
    /// </summary>
    public partial class OfflineCard
    {
        public static SerialPort SerialPort = null;
        string key = "yglock.com";//通讯数据密钥
        public static string des3Key = "Tt3rLPrDIVIhXqAz";// 长度控制为16，作为3DES加密用的key
        private HttpListener listener;
        private int currentRoomId;//当前选中的房间编号
        

        /// <summary>
        /// 离线卡
        /// </summary>
        public OfflineCard()
        {
            InitializeComponent();
            //查询酒店的房间信息
            GetRoomList();
            //获取串口并连接
            CheckSerialCommunication();
        }


        /// <summary>
        /// 定时检查通讯状况
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_card(object sender, EventArgs e)//计时执行的程序
        {
            //检查通讯状况
            if(null != SerialPort || SerialPort.IsOpen ==null || SerialPort.IsOpen==true)
            {
                AppConfigUtil.SetValue("SerialPort", "status", "1");
            }else
            {
                AppConfigUtil.SetValue("SerialPort", "status", "0");
            }

        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="command"></param>
        static void ExecuteCmdCommand(string command)
        {
            ProcessStartInfo processInfo = new ProcessStartInfo("cmd.exe");
            processInfo.UseShellExecute = true;
            processInfo.Verb = "runas";  // 以管理员权限运行
            processInfo.Arguments = $"/C {command}";  // 执行命令并关闭命令行窗口
            Process.Start(processInfo);
        }

        /// <summary>
        /// 获取酒店房间列表
        /// </summary>
        private void GetRoomList()
        {
            string hotelId = Encryptor.DecryptData(AppConfigUtil.GetValue("LoginUser", "hotelId"), des3Key);
            if (string.IsNullOrEmpty(hotelId))
            {
                WriteLog.Write(1, "未获取到酒店信息");
                return;
            }

            string data = HttpGet.Get(StrUtils.hotel_room_url + hotelId);
            if (string.IsNullOrEmpty(data))
            {
                Dispatcher.Invoke(
                    new Action(() =>
                    {
                        RoomList.ItemsSource = "";
                    }));
            }
            else
            {
                JObject obj = JObject.Parse(data);
                if (Convert.ToInt16(obj["code"]) == 200)
                {
                    
                    //string ACCESS_TOKEN = obj["data"].Value<string>("access_token");
                    Dispatcher.Invoke(
                    new Action(() =>
                    {
                        RoomList.ItemsSource = obj["data"];
                    }
                ));
                }
            }
        }

        /// <summary>
        /// 开始按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Btn_Start_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                string cardPort = AppConfigUtil.GetValue("SerialPort", "cardPort");
                string cardPortText = TextBox_Port.Text;
                if (string.IsNullOrEmpty(cardPort))
                {
                    MessageBox.Show("请填写需要使用得端口");
                    return;
                }
                // 确保以管理员权限运行应用程序
                if (string.IsNullOrEmpty(cardPort) || !StrUtils.IsInt(cardPort) || !cardPort.Equals(cardPortText))
                {
                    cardPort = cardPortText;
                    
                    List<string> ports = new List<string>();
                    ports.Add("netsh http delete urlacl url=http://*:" + cardPort + "/");
                    ports.Add("netsh http delete urlacl url=http://+:" + cardPort + "/");
                    ports.Add("netsh http add urlacl url=http://*:" + cardPort + "/  user=Everyone");
                    ports.Add("netsh http add urlacl url=http://+:" + cardPort + "/  user=Everyone");
                    ports.Add("netsh advfirewall firewall Add rule name=\"离线发卡器" + cardPort + "\" dir=in protocol=tcp localport=7777 action=allow");
                    for (int i = 0; i < ports.Count; i++)
                    {
                        // 执行 cmd 命令
                        ExecuteCmdCommand(ports[i]);
                    }
                    AppConfigUtil.SetValue("SerialPort","cardPort", cardPort);
                }
                

                // 创建一个 HttpListener 对象，监听本地地址
                listener = new HttpListener();
                listener.Prefixes.Add("http://+:" + cardPort + "/");


                // 启动服务器
                listener.Start();
                WriteLog.Write(0, "服务器正在运行...");
                // 接受并处理客户端请求
                while (true)
                {
                    // 等待请求
                    HttpListenerContext context = await listener.GetContextAsync();
                    // 处理请求
                    ThreadPool.QueueUserWorkItem((_) => HandleRequest(context));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);
            }
        }

        /// <summary>
        /// 处理请求的数据
        /// </summary>
        /// <param name="context"></param>
        private void HandleRequest(HttpListenerContext context)
        {
            // 获取请求的 URL
            string url = context.Request.Url.AbsolutePath;

            // 如果请求的 URL 是 "/hello"，则返回 "Hello, World!"
            if (url == "/hello")
            {
                HttpListenerRequest request = context.Request;
                // 获取查询字符串参数
                string name = request.QueryString.Get("name");
                string responseStr = "";
                if (string.IsNullOrEmpty(name))
                {
                    responseStr = "错误请求";

                }
                else
                {
                    responseStr = name;
                }
                // 获取表单数据
                if (request.HttpMethod == "POST" && request.ContentType == "application/x-www-form-urlencoded")
                {
                    using (System.IO.Stream body = request.InputStream)
                    {
                        using (System.IO.StreamReader reader = new System.IO.StreamReader(body, request.ContentEncoding))
                        {
                            string formData = reader.ReadToEnd();
                            Console.WriteLine($"Form Data: {formData}");
                        }
                    }
                }


                //响应数据
                byte[] response = System.Text.Encoding.UTF8.GetBytes("Hello, "+ responseStr + "!");
                context.Response.OutputStream.Write(response, 0, response.Length);
                context.Response.Close();
            }
            else
            {
                // 返回 404 Not Found
                context.Response.StatusCode = 404;
                context.Response.Close();
            }
        }

        /// <summary>
        /// 结束按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Btn_Stop_Click(object sender, RoutedEventArgs e)
        {
            listener.Stop();
            WriteLog.Write(0, "服务器正在停止...");
        }


        /// <summary>
        /// 获取串口名称
        /// </summary>
        /// <returns></returns>
        public string[] GetPortNames()
        {
            return SerialPort.GetPortNames();
        }


        /// <summary>
        /// 打开或关闭串口
        /// </summary>
        /// <param name="comName"></param>
        /// <param name="baud"></param>
        /// <returns></returns>
        public SerialPort OpenClosePort(string comName, int baud)
        {
            //串口未打开
            if (SerialPort == null || !SerialPort.IsOpen)
            {
                SerialPort = new SerialPort();
                //串口名称
                SerialPort.PortName = comName;
                //波特率
                SerialPort.BaudRate = baud;
                //数据位
                SerialPort.DataBits = 8;
                //停止位
                SerialPort.StopBits = StopBits.One;
                //检验位
                SerialPort.Parity = Parity.None;
                //打开串口
                SerialPort.Open();
                //串口数据接收事件实现
                SerialPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);
                return SerialPort;
            }
            //串口已打开
            else
            {
                SerialPort.Close();
                return SerialPort;
            }
        }

        /// <summary>
        /// 检查串口通讯
        /// </summary>
        public void CheckSerialCommunication()
        {
            //设置串口号信息为空
            AppConfigUtil.SetValue("SerialPort", "portName", "");
            //设置无效通讯状态
            AppConfigUtil.SetValue("SerialPort", "communicationStatus", Encryptor.EncryptData("0", des3Key));

            //获取串口名称
            string[] portNames = GetPortNames();
            List<string> portList = new List<string>();
            if (portNames != null)
            {
                foreach (string name in portNames)
                {
                    portList.Add(name);
                }
            }
            if (portList.Count == 0) //为空
            {
                return;
            }
            for (int i = 0; i < portList.Count; i++)
            {
                //打开串口
                SerialPort = OpenClosePort(portList[i], 115200);
                if (SerialPort != null && SerialPort.IsOpen)
                {
                    WriteLog.Write(0, "打开串口");
                    //发送握手协议数据
                    SendData(DoorLockEncryption.AssemblyData("", "", "", ""));
                    Thread.Sleep(2000);
                    //是否为有效连接
                    string communicationStatus = Encryptor.DecryptData(AppConfigUtil.GetValue("SerialPort", "communicationStatus"), des3Key);
                    if (communicationStatus.Equals("1"))
                    {
                        AppConfigUtil.SetValue("SerialPort", "status", "1");
                        //设置设备编码
                        string equipmentcode = Encryptor.DecryptData(AppConfigUtil.GetValue("SerialPort", "equipmentCode"), des3Key);
                        Debug.WriteLine("已经连接");
                        break;
                    }
                }
                else
                {
                    WriteLog.Write(0, "关闭串口");
                    AppConfigUtil.SetValue("SerialPort", "status", "0");
                }
            }
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void ReceiveData(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort _SerialPort = (SerialPort)sender;
            

            int _bytesToRead = _SerialPort.BytesToRead;
            byte[] recvData = new byte[_bytesToRead];
            _SerialPort.Read(recvData, 0, _bytesToRead);
            string receiveStr = ConverUtil.ToHexStrFromByte(recvData);
            //解密
            string result = DoorLockEncryption.decryptedContent(receiveStr, DoorLockEncryption.ConvertStringToHex(key));
            Debug.WriteLine("收到的数据："+result);
            WriteLog.Write(0, "收到数据==>" + result);
            //19 + N +1
            //36-2
            //头1  长度2 随机数4 时间戳4 设备编码6 协议版本1 命令1 数据N  校验1
            //A100000000000000000000FFFFFFFFFFFF011AB6
            //A1001600000000000000001234567890011AE001640000000000000000000000000000000000000000BB
            int count = DoorLockEncryption.CountOccurrences(result, "A1");
            while (true)
            {
                if (count > 0)
                {
                    int index = result.IndexOf("A1");
                    if (index != -1)
                    {
                        string len = result.Substring(index + 2, 4);
                        int dataLen = Convert.ToInt32(len, 16);//
                        string newData = result.Substring(index, 38 + dataLen * 2 + 2);
                        //1、获取握手协议并记录信息
                        string command = newData.Substring(36, 2);

                        int countLen = (19 + dataLen) * 2;
                        result = result.Substring(index + countLen + 2);
                        count = DoorLockEncryption.CountOccurrences(result, "A1");

                        switch (command)
                        {
                            case "1A"://握手协议
                                string portName = _SerialPort.PortName;//串口名称
                                AppConfigUtil.SetValue("SerialPort", "portName", Encryptor.EncryptData(portName, des3Key));//设置串口号
                                AppConfigUtil.SetValue("SerialPort", "communicationStatus", Encryptor.EncryptData("1", des3Key));//标记为有效通信
                                string equipmentcode = newData.Substring(22, 12);
                                AppConfigUtil.SetValue("SerialPort", "equipmentCode", Encryptor.EncryptData(equipmentcode, des3Key));//设置设备编码
                                count = 0;
                                break;
                        }
                    }
                }
                else
                {
                    break;
                }
            }
            
        }
        
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool SendData(string content)
        {
            //加密
            content=DoorLockEncryption.encryptedHex(content, DoorLockEncryption.ConvertStringToHex(key));
            byte[] data = ConverUtil.ToHexByteArray(content);
            if (SerialPort != null && SerialPort.IsOpen)
            {
                SerialPort.Write(data, 0, data.Length);
                WriteLog.Write(0, "发送数据==>" + ConverUtil.ToHexString(data));
                return true;
            }
            else
            {
                return false;
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            string platText = HexText.Text;
            //加密数据
            SendData(platText);
        }

        /// <summary>
        /// 获取点击得房间信息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GetRoomInfo(object sender, MouseButtonEventArgs e)
        {
            TextBlock? s = sender as TextBlock;
            if (s != null)
            {
                JObject obj = JObject.Parse(s.Tag.ToString());
                if(null == obj)
                {
                    MessageBox.Show("数据异常");
                    return;
                }
                OfflineCardModel ocm = new OfflineCardModel();
                ocm.RoomId = Convert.ToInt32(obj["roomId"]);
                ocm.Room = Convert.ToString(obj["room"]);
                ocm.DoorLockSerial = Convert.ToString(obj["doorLockSerial"]);
                ocm.BuildingId= Convert.ToInt32(obj["buildingId"]);
                ocm.Building = Convert.ToString(obj["building"]);
                ocm.FloorId= Convert.ToInt32(obj["floorId"]);
                ocm.Floor = Convert.ToString(obj["floor"]);

                currentRoomId = ocm.RoomId;
                ShowAlertUtil.ShowAlert("点击的房间编号:" + currentRoomId);
            }
        }

        /// <summary>
        /// 加载执行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OfflineCard_Loaded(object sender, RoutedEventArgs e)
        {
            //定时任务创建
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = new TimeSpan(0, 10, 0);//设置的间隔为一分钟
            timer.Tick += timer_card;
            timer.IsEnabled = true;
            timer.Start();
        }
    }
}
